package my.mybatis.common.util;

import my.mybatis.common.QueryParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @Author:wangbin.
 * @Description.
 * @Date:Created in 10:50 2017/9/18.
 * @Modified By:
 */
public class QueryValueConventor {
    private static final Logger LOGGER = LoggerFactory.getLogger(QueryValueConventor.class);
    private static ConcurrentMap<String,ConcurrentMap<String,Class>> cacheFieldMap;

    static {
        cacheFieldMap = new ConcurrentHashMap<String,ConcurrentMap<String,Class>>();
    }

    private static void putCacheField(Class clazz)
    {
        if(cacheFieldMap.get(clazz.toString()) == null)
        {
            ConcurrentMap<String,Class> map = new ConcurrentHashMap<String,Class>();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields)
                map.putIfAbsent(field.getName(),field.getType());
            cacheFieldMap.putIfAbsent(clazz.toString(),map);
        }
    }

    private static Class getTypeByFieldName(Class clazz,String fieldName)
    {
        if(cacheFieldMap.get(clazz.toString()) == null)
            putCacheField(clazz);
        return cacheFieldMap.get(clazz.toString()).get(fieldName);
    }

    /**
     * value 转型
     * @param clazz
     * @param value
     * @return
     */
    private static Object conversionValue(Class clazz, Object value)
    {
        if(clazz == String.class)
            return value.toString();
        if(clazz == Integer.class)
            return Integer.parseInt(value.toString());
        if(clazz == Long.class)
            return Long.parseLong(value.toString());
        if(clazz == Short.class)
            return Short.parseShort(value.toString());
        if(clazz == Byte.class)
            return Byte.parseByte(value.toString());
        if(clazz == Double.class)
            return Double.parseDouble(value.toString());
        if(clazz == Float.class)
            return Float.parseFloat(value.toString());
        if(clazz == Date.class)
        {
            try {
                return DateSyncUtil.parse(value.toString());
            } catch (ParseException e) {
                try {
                    return DateSyncUtil.parse_ymd(value.toString());
                } catch (ParseException e1) {
                    LOGGER.error("conversionValue ~~~~~~~~~~日期条件转换错误~~~~~~~~~~");
                    e1.printStackTrace();
                }
            }
        }
        if(clazz == List.class)
            return (List)value;
        return value;
    }

    public static Object get(Class clazz,String fieldName, Object value)
    {
        /**
         * 判断字段类型如果不一致要转型
         */
        if(getTypeByFieldName(clazz,fieldName) != value.getClass())
            return conversionValue(getTypeByFieldName(clazz,fieldName),value);
        return value;
    }

    public static Object get(Object value)
    {
        /**
         * 判断字段类型如果不一致要转型
         */
        if(value.getClass() == List.class)
            return (List)value;
        if(value.getClass() == ArrayList.class)
            return (ArrayList)value;
        return value;
    }

    /**
     * 条件为 OperatorConventor.EQ，类型为{@link Date} 的查询条件的处理
     * @param queryParam
     * @param dateEqlDealList
     * @return
     */
    public static boolean convertQueryParam(Class clazz, QueryParam queryParam, List<QueryParam> dateEqlDealList)
    {
        String fileName = queryParam.getKey();
        String operator = queryParam.getOperator();
        Object value = queryParam.getValue();
        Class clz = getTypeByFieldName(clazz,fileName);
        if(OperatorConventor.EQ.equals(operator.toLowerCase()) && clz == Date.class)
        {
            String dateString = value.toString();
            try {
                String convertDateString = DateSyncUtil.formatDate_ymd(DateSyncUtil.parse_ymd(dateString));
                String lowDate = convertDateString + " 00:00:00";
                String upDate = convertDateString + " 23:59:59";
                dateEqlDealList.add(QueryBuildFactory.createQueryParam().key(fileName).operator(OperatorConventor.GE).value(lowDate).build());
                dateEqlDealList.add(QueryBuildFactory.createQueryParam().key(fileName).operator(OperatorConventor.LE).value(upDate).build());
            } catch (ParseException e) {
                LOGGER.error("convertSearchParam ~~~~~~~~~~日期条件转换错误~~~~~~~~~~");
                e.printStackTrace();
            }
            return true;
        }
        return false;
    }

    private QueryValueConventor(){}

    private static class InnerClass
    {
        private static final QueryValueConventor SERACH_PARAM_VALUE_CONVERSION = new QueryValueConventor();
    }

    public static QueryValueConventor getInstance()
    {
        return InnerClass.SERACH_PARAM_VALUE_CONVERSION;
    }
}
